Packages

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────────────────────── tidyverse 1.3.2 ──✔ tibble  3.2.1     ✔ stringr 1.5.0
✔ readr   2.1.3     ✔ forcats 1.0.0
✔ purrr   1.0.1     ── Conflicts ──────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::extract() masks raster::extract()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
✖ purrr::map()     masks maps::map()
✖ dplyr::select()  masks raster::select()
library(sf)
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is TRUE
library(here)
here() starts at /Users/ramkripa
library(weed)
library(rnaturalearth)
library(rnaturalearthdata)

Attaching package: ‘rnaturalearthdata’

The following object is masked from ‘package:rnaturalearth’:

    countries110

Loading In the Data

emdat <- read_csv('~/Desktop/projects/emdat_proj/full_emdat_geocoded_finally.csv')
Warning: One or more parsing issues, call `problems()` on your data frame for details, e.g.:
  dat <- vroom(...)
  problems(dat)Rows: 74035 Columns: 51── Column specification ──────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (27): Dis No, Seq, Disaster Group, Disaster Subgroup, Disaster Type, Disaster Subtype, Disast...
dbl  (18): Year, Dis Mag Value, Start Year, Start Month, Start Day, End Year, End Month, End Day, ...
lgl   (5): Glide, Aid Contribution, Reconstruction Costs ('000 US$), Admin1 Code, uncertain_locati...
time  (1): Local Time
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

How many disasters were located?

How many locations were located?

All types of disasters

Restrict to dry and wet hydrological disasters

dry_list <- c("Drought", "Extreme temperature", "Wildfire")
wet_list <- c("Flood", "Landslide", "Storm")

emdat_hydrological <- emdat %>%
  filter((`Disaster Type` %in% dry_list) || (`Disaster Type` %in% wet_list)) %>%
  mutate(dry = (`Disaster Type` %in% dry_list), wet = (`Disaster Type` %in% wet_list))
Warning: There were 2 warnings in `filter()`.
The first warning was:
ℹ In argument: `(`Disaster Type` %in% dry_list) || ...`.
Caused by warning in `` (`Disaster Type` %in% dry_list) || (`Disaster Type` %in% wet_list) ``:
! 'length(x) = 74035 > 1' in coercion to 'logical(1)'
ℹ Run ]8;;ide:run:dplyr::last_dplyr_warnings()dplyr::last_dplyr_warnings()]8;; to see the 1 remaining warning.

ENSO data

enso_data <- read_csv('~/Desktop/projects/emdat_proj/data/enso_data_copy2.csv')
Rows: 812 Columns: 7── Column specification ─────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): MonthTxt, PeriodTxt, PeriodNum, Event
dbl (3): Year, MonthNum, Value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
enso_data %>%
  group_by(Event) %>%
  count()
emdat_hydrological_enso %>%
  filter(!is.na(enso_Value)) %>%
  filter(!is.na(wet)) %>%
  mutate(enso_positive = (enso_Value > 0)) %>%
  group_by(`Dis No`) %>%
  summarize(enso_pos = any(enso_positive),enso_val = mean(enso_Value), is_wet = any(wet)) %>%
  ggplot(mapping = aes(x = enso_val, fill = is_wet)) +
    geom_histogram(stat = "density") +
    facet_grid(~is_wet) +
  ggtitle("Counts of Disasters compared to value of ONI with wet disasters in Blue and Dry in Red")
Warning: Ignoring unknown parameters: `binwidth`, `bins`, and `pad`

resy <- 2.5

emdat_hydrological_enso %>%
  left_join(event_num_months, by = c("Event")) %>%
  filter(!is.na(enso_Value)) %>%
  filter(!is.na(wet)) %>%
  filter(!is.na(lat)) %>%
  mutate(wet_factor = as_factor(wet)) %>%
  mutate(Event_factor = fct_recode(as_factor(Event), no_event = "N", negative = "-", positive = "+")) %>%
  mutate(wet_string = fct_recode(wet_factor, wet_disasters = "TRUE", dry_disasters = "FALSE")) %>%
  mutate(lat_box = (as.integer(lat) %/% resy) * resy , lng_box = (as.integer(lng) %/% resy) * resy) %>%
  mutate(dis_no_factor = as_factor(`Dis No`)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string, dis_no_factor) %>%
  summarize(num_months = first(num_months), num_disaster_month = mean(num_months_disaster)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string) %>%
  summarize(num_months = first(num_months), num_disaster_months = sum(num_disaster_month)) %>%
  mutate(disaster_rate = num_disaster_months / num_months) %>%
  pivot_wider(id_cols = c(lat_box, lng_box), names_from = c(Event_factor, wet_string), values_from = c(disaster_rate), values_fill = 0) %>%
  mutate(positive_wet_relative_risk = positive_wet_disasters / no_event_wet_disasters, 
         negative_wet_relative_risk = negative_wet_disasters / no_event_wet_disasters, 
         positive_dry_relative_risk =  positive_dry_disasters / no_event_dry_disasters,
         negative_dry_relative_risk = negative_dry_disasters / no_event_dry_disasters) %>%
  select(lat_box, lng_box, positive_wet_relative_risk, negative_wet_relative_risk, positive_dry_relative_risk, negative_dry_relative_risk) %>%
  pivot_longer(cols = c(positive_wet_relative_risk, negative_wet_relative_risk, positive_dry_relative_risk, negative_dry_relative_risk), names_to = 'risk', values_to = 'value') %>%
  mutate(risk_factor = as_factor(risk), values_cleaned = if_else(is.infinite(value), 18, value)) %>%
  mutate(relative_risk_cleaned = if_else(is.nan(values_cleaned), 1, values_cleaned)) %>%
  mutate(relative_risk_cleaned2 = if_else((relative_risk_cleaned) > 2, 2, relative_risk_cleaned)) %>%
  ggplot() +
  geom_sf(data = world_map) +
  geom_tile(mapping = aes(x = lng_box, y = lat_box, fill = relative_risk_cleaned2, width = resy)) +
  scale_fill_gradient2(midpoint = 1, limits = c(0, 2), low = 'cyan', high = 'red') +
  facet_grid(rows = vars(risk_factor))+
  ggtitle("Relative risk plot using calculations of the form [{num_disasters_positive_wet / num_months_positive} / {num_disasters_no_event_wet / num_months_no_event}]")
`summarise()` has grouped output by 'lat_box', 'lng_box', 'Event_factor', 'wet_string'. You can override using the `.groups` argument.`summarise()` has grouped output by 'lat_box', 'lng_box', 'Event_factor'. You can override using the `.groups` argument.

## calculate percent of total disasters within each box
### create boxes 2x2

resy <- 2.5

emdat_hydrological_enso %>%
  left_join(event_num_months, by = c("Event")) %>%
  filter(!is.na(enso_Value)) %>%
  filter(!is.na(wet)) %>%
  filter(!is.na(lat)) %>%
  mutate(wet_factor = as_factor(wet)) %>%
  mutate(Event_factor = fct_recode(as_factor(Event), no_event = "N", negative = "-", positive = "+")) %>%
  mutate(wet_string = fct_recode(wet_factor, wet_disasters = "TRUE", dry_disasters = "FALSE")) %>%
  mutate(lat_box = (as.integer(lat) %/% resy) * resy , lng_box = (as.integer(lng) %/% resy) * resy) %>%
  mutate(dis_no_factor = as_factor(`Dis No`)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string, dis_no_factor) %>%
  summarize(num_months = first(num_months), num_disaster_month = mean(num_months_disaster)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string) %>%
  summarize(num_months = first(num_months), num_disaster_months = sum(num_disaster_month)) %>%
  mutate(disaster_rate = num_disaster_months / num_months) %>%
  pivot_wider(id_cols = c(lat_box, lng_box), names_from = c(Event_factor, wet_string), values_from = c(disaster_rate), values_fill = 0) %>%
  mutate(positive_wet_percent = positive_wet_disasters / (no_event_wet_disasters + positive_wet_disasters + negative_wet_disasters) , 
         negative_wet_percent = negative_wet_disasters / (no_event_wet_disasters + positive_wet_disasters + negative_wet_disasters), 
         positive_dry_percent =  positive_dry_disasters / (no_event_dry_disasters + positive_dry_disasters + negative_dry_disasters),
         negative_dry_percent =  negative_dry_disasters / (no_event_dry_disasters + positive_dry_disasters + negative_dry_disasters)
         ) %>%
  select(lat_box, lng_box, positive_wet_percent, negative_wet_percent, positive_dry_percent, negative_dry_percent) %>%
  pivot_longer(cols = c(positive_wet_percent, negative_wet_percent, positive_dry_percent, negative_dry_percent), names_to = 'typey', values_to = 'value') %>%
  mutate(type_factor = as_factor(typey), values = if_else(is.nan(value), 0, value)) %>%
  ggplot() +
  geom_sf(data = world_map) +
  geom_tile(mapping = aes(x = lng_box, y = lat_box, fill = values, width = resy)) +
  scale_fill_gradient(low = 'white', high = 'red') +
  facet_grid(rows = vars(type_factor))+
  ggtitle("Disaster Percent plot using calculations of the form [positive_wet / all_wet]")
  
emdat_hydrological_enso %>%
  mutate(spring_summery = as_factor((end_month >= 4) & (end_month <= 9))) %>%
  mutate(half_year = fct_recode(spring_summery, spring_summer = "TRUE", fall_winter = "FALSE")) %>%
  left_join(event_half_num_months, by = c("Event", "half_year")) %>%
  filter(!is.na(enso_Value)) %>%
  filter(!is.na(wet)) %>%
  filter(!is.na(lat)) %>%
  mutate(wet_factor = as_factor(wet)) %>%
  mutate(Event_factor = fct_recode(as_factor(Event), no_event = "N", negative = "-", positive = "+")) %>%
  mutate(wet_string = fct_recode(wet_factor, wet_disasters = "TRUE", dry_disasters = "FALSE")) %>%
  mutate(lat_box = (as.integer(lat) %/% resy) * resy , lng_box = (as.integer(lng) %/% resy) * resy) %>%
  mutate(dis_no_factor = as_factor(`Dis No`)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string, dis_no_factor, half_year) %>%
  summarize(num_months = first(num_months), num_disaster_month = mean(num_months_disaster)) %>%
  group_by(lat_box, lng_box, Event_factor, wet_string, half_year) %>%
  summarize(num_months = first(num_months), num_disaster_months = sum(num_disaster_month)) %>%
  mutate(disaster_rate = num_disaster_months / num_months) %>%
  pivot_wider(id_cols = c(lat_box, lng_box, half_year), names_from = c(Event_factor, wet_string), values_from = c(disaster_rate), values_fill = 0) %>%
  mutate(positive_wet_relative_risk = positive_wet_disasters / no_event_wet_disasters, 
         negative_wet_relative_risk = negative_wet_disasters / no_event_wet_disasters, 
         positive_dry_relative_risk =  positive_dry_disasters / no_event_dry_disasters,
         negative_dry_relative_risk = negative_dry_disasters / no_event_dry_disasters) %>%
  select(lat_box, lng_box, half_year, positive_wet_relative_risk, negative_wet_relative_risk, positive_dry_relative_risk, negative_dry_relative_risk) %>%
  pivot_longer(cols = c(positive_wet_relative_risk, negative_wet_relative_risk, positive_dry_relative_risk, negative_dry_relative_risk), names_to = 'risk', values_to = 'value') %>%
  mutate(risk_factor = as_factor(risk), values_cleaned = if_else(is.infinite(value), 18, value)) %>%
  mutate(relative_risk_cleaned = if_else(is.nan(values_cleaned), 1, values_cleaned)) %>%
  mutate(relative_risk_cleaned_truncatedat2 = if_else((relative_risk_cleaned) > 2, 2, relative_risk_cleaned)) %>%
  select(lat_box, lng_box, half_year, risk_factor, relative_risk_cleaned, relative_risk_cleaned_truncatedat2) %>%
  ggplot() +
  geom_sf(data = world_map) +
  geom_tile(mapping = aes(x = lng_box, y = lat_box, fill = relative_risk_cleaned_truncatedat2, width = resy)) +
  scale_fill_gradient2(midpoint = 1, limits = c(0, 2), low = 'cyan', high = 'red') +
  facet_grid(rows = vars(risk_factor), cols = vars(half_year))+
  ggtitle("Half year Relative risk plot using calculations of the form [{num_disasters_positive_wet / num_months_positive} / {num_disasters_no_event_wet / num_months_no_event}]")
`summarise()` has grouped output by 'lat_box', 'lng_box', 'Event_factor', 'wet_string', 'dis_no_factor'. You can override using the `.groups` argument.`summarise()` has grouped output by 'lat_box', 'lng_box', 'Event_factor', 'wet_string'. You can override using the `.groups` argument.

LS0tCnRpdGxlOiAiRU5TTyBhbmFseXNpcyBuZXciCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKIyMgUGFja2FnZXMKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShzZikKbGlicmFyeShoZXJlKQpsaWJyYXJ5KHdlZWQpCmxpYnJhcnkocm5hdHVyYWxlYXJ0aCkKbGlicmFyeShybmF0dXJhbGVhcnRoZGF0YSkKYGBgCgojIyBMb2FkaW5nIEluIHRoZSBEYXRhCgpgYGB7cn0KZW1kYXQgPC0gcmVhZF9jc3YoJ34vRGVza3RvcC9wcm9qZWN0cy9lbWRhdF9wcm9qL2Z1bGxfZW1kYXRfZ2VvY29kZWRfZmluYWxseS5jc3YnKQpgYGAKIyBIb3cgbWFueSBkaXNhc3RlcnMgd2VyZSBsb2NhdGVkPwoKYGBge3J9CmVtZGF0ICU+JQogIHBlcmNlbnRfbG9jYXRlZF9kaXNhc3RlcnMocGxvdF9yZXN1bHQ9RkFMU0UpCmBgYAoKIyBIb3cgbWFueSBsb2NhdGlvbnMgd2VyZSBsb2NhdGVkPwoKYGBge3J9CmVtZGF0ICU+JQogIHBlcmNlbnRfbG9jYXRlZF9sb2NhdGlvbnMocGxvdF9yZXN1bHQ9RkFMU0UpCmBgYAojIEFsbCB0eXBlcyBvZiBkaXNhc3RlcnMKCmBgYHtyfQplbWRhdCAlPiUKICBncm91cF9ieShgRGlzYXN0ZXIgVHlwZWApICU+JQogIGNvdW50KCkKYGBgCgojIFJlc3RyaWN0IHRvIGRyeSBhbmQgd2V0IGh5ZHJvbG9naWNhbCBkaXNhc3RlcnMKCmBgYHtyfQpkcnlfbGlzdCA8LSBjKCJEcm91Z2h0IiwgIkV4dHJlbWUgdGVtcGVyYXR1cmUiLCAiV2lsZGZpcmUiKQp3ZXRfbGlzdCA8LSBjKCJGbG9vZCIsICJMYW5kc2xpZGUiLCAiU3Rvcm0iKQoKZW1kYXRfaHlkcm9sb2dpY2FsIDwtIGVtZGF0ICU+JQogIGZpbHRlcihgRGlzYXN0ZXIgVHlwZWAgJWluJSBjKGRyeV9saXN0LCB3ZXRfbGlzdCkpICU+JQogIG11dGF0ZShkcnkgPSAoYERpc2FzdGVyIFR5cGVgICVpbiUgZHJ5X2xpc3QpLCB3ZXQgPSAoYERpc2FzdGVyIFR5cGVgICVpbiUgd2V0X2xpc3QpKQpgYGAKCmBgYHtyfQplbWRhdF9oeWRyb2xvZ2ljYWwgJT4lCiAgZ3JvdXBfYnkoYERpc2FzdGVyIFR5cGVgKSAlPiUKICBjb3VudCgpCmBgYAoKIyBFTlNPIGRhdGEKCmBgYHtyfQplbnNvX2RhdGEgPC0gcmVhZF9jc3YoJ34vRGVza3RvcC9wcm9qZWN0cy9lbWRhdF9wcm9qL2RhdGEvZW5zb19kYXRhX2NvcHkyLmNzdicpCmVuc29fZGF0YSAlPiUKICBncm91cF9ieShFdmVudCkgJT4lCiAgY291bnQoKQpgYGAKCmBgYHtyfQplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyA8LSBlbWRhdF9oeWRyb2xvZ2ljYWwgJT4lCiAgZnVsbF9qb2luKGVuc29fZGF0YSwgYnkgPSBjKCJZZWFyIiA9ICJZZWFyIiwgIlN0YXJ0IE1vbnRoIiA9ICJNb250aE51bSIpKSAlPiUKICByZW5hbWUoImVuc29fVmFsdWUiID0gIlZhbHVlIikgJT4lCiAgZmlsdGVyKCFpcy5uYShgU3RhcnQgTW9udGhgKSkgJT4lCiAgbXV0YXRlKHN0YXJ0X3llYXIgPSBpZl9lbHNlKGlzLm5hKGBTdGFydCBZZWFyYCksIFllYXIsIGBTdGFydCBZZWFyYCkpICU+JQogIG11dGF0ZShlbmRfeWVhciA9IGlmX2Vsc2UoaXMubmEoYEVuZCBZZWFyYCksIHN0YXJ0X3llYXIsIGBFbmQgWWVhcmApKSAlPiUKICBtdXRhdGUoZW5kX21vbnRoID0gaWZfZWxzZShpcy5uYShgRW5kIE1vbnRoYCksIGBTdGFydCBNb250aGAsIGBFbmQgTW9udGhgKSkgJT4lCiAgbXV0YXRlKG51bV9tb250aHNfZGlzYXN0ZXIgPSAoZW5kX21vbnRoIC0gYFN0YXJ0IE1vbnRoYCArIDEpICsgMTIgKiAoZW5kX3llYXIgLSBzdGFydF95ZWFyKSkgJT4lCiAgZmlsdGVyKG51bV9tb250aHNfZGlzYXN0ZXIgPiAwKQoKZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgZ3JvdXBfYnkobnVtX21vbnRoc19kaXNhc3RlcikgJT4lCiAgc3VtbWFyaXplKGNvdW50X2Rpc2FzdGVycyA9IG5fZGlzdGluY3QoYERpcyBOb2ApKQpgYGAKCmBgYHtyfQplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyAlPiUKICBmaWx0ZXIoIWlzLm5hKGVuc29fVmFsdWUpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHdldCkpICU+JQogIG11dGF0ZShlbnNvX3Bvc2l0aXZlID0gKGVuc29fVmFsdWUgPiAwKSkgJT4lCiAgZ3JvdXBfYnkoYERpcyBOb2ApICU+JQogIHN1bW1hcml6ZShlbnNvX3BvcyA9IGFueShlbnNvX3Bvc2l0aXZlKSxlbnNvX3ZhbCA9IG1lYW4oZW5zb19WYWx1ZSksIGlzX3dldCA9IGFueSh3ZXQpKSAlPiUKICBnZ3Bsb3QobWFwcGluZyA9IGFlcyh4ID0gZW5zb192YWwsIGZpbGwgPSBpc193ZXQpKSArCiAgICBnZW9tX2hpc3RvZ3JhbShzdGF0ID0gImRlbnNpdHkiKSArCiAgICBmYWNldF9ncmlkKH5pc193ZXQpICsKICBnZ3RpdGxlKCJDb3VudHMgb2YgRGlzYXN0ZXJzIGNvbXBhcmVkIHRvIHZhbHVlIG9mIE9OSSB3aXRoIHdldCBkaXNhc3RlcnMgaW4gQmx1ZSBhbmQgRHJ5IGluIFJlZCIpCmBgYApgYGB7cn0KZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICAjbXV0YXRlKGVuc29fcG9zaXRpdmUgPSAoZW5zb19WYWx1ZSA+IDApKSAlPiUKICBncm91cF9ieShgRGlzIE5vYCkgJT4lCiAgc3VtbWFyaXplKGVuc29fZXZlbnQgPSBmaXJzdChFdmVudCksZW5zb192YWwgPSBtZWFuKGVuc29fVmFsdWUpLCBpc193ZXQgPSBhbnkod2V0KSwgaXNfZHJ5ID0gYW55KGRyeSkpICU+JQogIG11dGF0ZShpc193ZXRfbnVtID0gYXMubnVtZXJpYyhpc193ZXQpLCBpc19kcnlfbnVtID0gYXMubnVtZXJpYyhpc19kcnkpKSAlPiUKICBncm91cF9ieShlbnNvX2V2ZW50KSAlPiUKICBzdW1tYXJpemUobnVtX2Rpc2FzdGVyc193ZXQgPSBzdW0oaXNfd2V0X251bSksIG51bV9kaXNhc3RlcnNfZHJ5ID0gc3VtKGlzX2RyeV9udW0pKQpgYGAKYGBge3J9CndvcmxkX21hcCA8LSBybmF0dXJhbGVhcnRoOjpuZV9jb3VudHJpZXMoc2NhbGUgPSAibWVkaXVtIiwgcmV0dXJuY2xhc3MgPSAic2YiKQoKZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGxhdCkpICU+JQogIG11dGF0ZShlbnNvX3Bvc2l0aXZlID0gKGVuc29fVmFsdWUgPiAwKSkgJT4lCiAgbXV0YXRlKHdldF9mYWN0b3IgPSBhc19mYWN0b3Iod2V0KSkgJT4lCiAgbXV0YXRlKHdldF9zdHJpbmcgPSBmY3RfcmVjb2RlKHdldF9mYWN0b3IsIHdldF9kaXNhc3RlcnMgPSAiVFJVRSIsIGRyeV9kaXNhc3RlcnMgPSAiRkFMU0UiKSkgJT4lCiAgc2VsZWN0KGxuZywgbGF0LCBlbnNvX1ZhbHVlLCB3ZXRfc3RyaW5nKSAlPiUKICAjaGVhZChuID0gNTBMKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gd29ybGRfbWFwKSArCiAgZ2VvbV90aWxlKG1hcHBpbmcgPSBhZXMoeCA9IGxuZywgeSA9IGxhdCwgZmlsbCA9IGVuc29fVmFsdWUsIHdpZHRoID0gMiwgaGVpZ2h0ID0gMikpICsKICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3c9ImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIpICsKICBmYWNldF9ncmlkKH53ZXRfc3RyaW5nKQogIAoKYGBgCmBgYHtyfQoKZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGxhdCkpICU+JQogIG11dGF0ZSh3ZXRfZmFjdG9yID0gYXNfZmFjdG9yKHdldCkpICU+JQogIG11dGF0ZShFdmVudF9mYWN0b3IgPSBmY3RfcmVjb2RlKGFzX2ZhY3RvcihFdmVudCksIG5vX2V2ZW50ID0gIk4iLCBuZWdhdGl2ZSA9ICItIiwgcG9zaXRpdmUgPSAiKyIpKSAlPiUKICBtdXRhdGUod2V0X3N0cmluZyA9IGZjdF9yZWNvZGUod2V0X2ZhY3Rvciwgd2V0X2Rpc2FzdGVycyA9ICJUUlVFIiwgZHJ5X2Rpc2FzdGVycyA9ICJGQUxTRSIpKSAlPiUKICBzZWxlY3QobG5nLCBsYXQsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZywgd2V0KSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gd29ybGRfbWFwKSArCiAgZ2VvbV90aWxlKG1hcHBpbmcgPSBhZXMoeCA9IGxuZywgeSA9IGxhdCwgd2lkdGggPSAyLCBoZWlnaHQgPSAyLCBmaWxsID0gMSwgYWxwaGEgPSAwLjAwMSkpICsKICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKHdldF9zdHJpbmcpLCByb3dzID0gdmFycyhFdmVudF9mYWN0b3IpKQoKYGBgCmBgYHtyfQoKZXZlbnRfbnVtX21vbnRocyA8LSBlbnNvX2RhdGEgJT4lCiAgZ3JvdXBfYnkoRXZlbnQpICU+JQogIHN1bW1hcml6ZShudW1fbW9udGhzID0gbigpKQoKZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgbGVmdF9qb2luKGV2ZW50X251bV9tb250aHMsIGJ5ID0gYygiRXZlbnQiKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGxhdCkpICU+JQogIG11dGF0ZSh3ZXRfZmFjdG9yID0gYXNfZmFjdG9yKHdldCkpICU+JQogIG11dGF0ZShFdmVudF9mYWN0b3IgPSBmY3RfcmVjb2RlKGFzX2ZhY3RvcihFdmVudCksIG5vX2V2ZW50ID0gIk4iLCBuZWdhdGl2ZSA9ICItIiwgcG9zaXRpdmUgPSAiKyIpKSAlPiUKICBtdXRhdGUod2V0X3N0cmluZyA9IGZjdF9yZWNvZGUod2V0X2ZhY3Rvciwgd2V0X2Rpc2FzdGVycyA9ICJUUlVFIiwgZHJ5X2Rpc2FzdGVycyA9ICJGQUxTRSIpKSAlPiUKICBzZWxlY3QobG5nLCBsYXQsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZywgbnVtX21vbnRocywgbnVtX21vbnRoc19kaXNhc3RlcikgJT4lCiAgYWRkX3JvdyhsbmcgPSAxLCBsYXQgPSAxLCBFdmVudF9mYWN0b3IgPSAnbm9fZXZlbnQnLCB3ZXRfc3RyaW5nID0gJ2RyeV9kaXNhc3RlcnMnLCBudW1fbW9udGhzID0gMSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IHdvcmxkX21hcCkgKwogIGdlb21fdGlsZShtYXBwaW5nID0gYWVzKHggPSBsbmcsIHkgPSBsYXQsIHdpZHRoID0gMiwgaGVpZ2h0ID0gMiwgYWxwaGEgPSBudW1fbW9udGhzX2Rpc2FzdGVyL251bV9tb250aHMsIGZpbGwgPSAncmVkJykpICsKICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKHdldF9zdHJpbmcpLCByb3dzID0gdmFycyhFdmVudF9mYWN0b3IpKSArCiAgZ2d0aXRsZSgiU2FtZSBwbG90IGFzIGFib3ZlIGJ1dCBzY2FsZWQgYnkgbnVtIG1vbnRocyIpCgpgYGAKCmBgYHtyfQplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyAlPiUKICBsZWZ0X2pvaW4oZXZlbnRfbnVtX21vbnRocywgYnkgPSBjKCJFdmVudCIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGVuc29fVmFsdWUpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHdldCkpICU+JQogIGZpbHRlcighaXMubmEobGF0KSkgJT4lCiAgbXV0YXRlKHdldF9mYWN0b3IgPSBhc19mYWN0b3Iod2V0KSkgJT4lCiAgbXV0YXRlKEV2ZW50X2ZhY3RvciA9IGZjdF9yZWNvZGUoYXNfZmFjdG9yKEV2ZW50KSwgbm9fZXZlbnQgPSAiTiIsIG5lZ2F0aXZlID0gIi0iLCBwb3NpdGl2ZSA9ICIrIikpICU+JQogIG11dGF0ZSh3ZXRfc3RyaW5nID0gZmN0X3JlY29kZSh3ZXRfZmFjdG9yLCB3ZXRfZGlzYXN0ZXJzID0gIlRSVUUiLCBkcnlfZGlzYXN0ZXJzID0gIkZBTFNFIikpICU+JQogIHNlbGVjdChsbmcsIGxhdCwgRXZlbnRfZmFjdG9yLCB3ZXRfc3RyaW5nLCBudW1fbW9udGhzKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gd29ybGRfbWFwKSArCiAgc3RhdF9iaW5fMmQobWFwcGluZyA9IGFlcyh4ID0gbG5nLCB5ID0gbGF0KSwgYmlud2lkdGggPSBjKDIsMikpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KHRyYW5zID0gJ2xvZycsIGxvdyA9ICd3aGl0ZScsIGhpZ2ggPSAncmVkJykgKyAKICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKHdldF9zdHJpbmcpLCByb3dzID0gdmFycyhFdmVudF9mYWN0b3IpKSArCiAgZ2d0aXRsZSgiMkQgSGlzdG9ncmFtIENvdW50cyAiKQoKYGBgCmBgYHtyfQoKZW1kYXRfaHlkcm9sb2dpY2FsX2Vuc28gJT4lCiAgbGVmdF9qb2luKGV2ZW50X251bV9tb250aHMsIGJ5ID0gYygiRXZlbnQiKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGxhdCkpICU+JQogIG11dGF0ZSh3ZXRfZmFjdG9yID0gYXNfZmFjdG9yKHdldCkpICU+JQogIG11dGF0ZShFdmVudF9mYWN0b3IgPSBmY3RfcmVjb2RlKGFzX2ZhY3RvcihFdmVudCksIG5vX2V2ZW50ID0gIk4iLCBuZWdhdGl2ZSA9ICItIiwgcG9zaXRpdmUgPSAiKyIpKSAlPiUKICBtdXRhdGUod2V0X3N0cmluZyA9IGZjdF9yZWNvZGUod2V0X2ZhY3Rvciwgd2V0X2Rpc2FzdGVycyA9ICJUUlVFIiwgZHJ5X2Rpc2FzdGVycyA9ICJGQUxTRSIpKSAlPiUKICBzZWxlY3QobG5nLCBsYXQsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZywgbnVtX21vbnRocykgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IHdvcmxkX21hcCkgKwogIHN0YXRfYmluXzJkKG1hcHBpbmcgPSBhZXMoeCA9IGxuZywgeSA9IGxhdCwgZmlsbCA9IC4uZGVuc2l0eS4uKSwgYmlud2lkdGggPSBjKDIsMikpICsKICBzY2FsZV9maWxsX2dyYWRpZW50KHRyYW5zID0gJ2xvZycsIGxvdyA9ICd3aGl0ZScsIGhpZ2ggPSAncmVkJykgKyAKICBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKHdldF9zdHJpbmcpLCByb3dzID0gdmFycyhFdmVudF9mYWN0b3IpKSArCiAgZ2d0aXRsZSgiMkQgSGlzdG9ncmFtIERlbnNpdHkiKQoKYGBgCgpgYGB7cn0KCmVtZGF0X2h5ZHJvbG9naWNhbF9lbnNvICU+JQogIGxlZnRfam9pbihldmVudF9udW1fbW9udGhzLCBieSA9IGMoIkV2ZW50IikpICU+JQogIGZpbHRlcighaXMubmEoZW5zb19WYWx1ZSkpICU+JQogIGZpbHRlcighaXMubmEod2V0KSkgJT4lCiAgZmlsdGVyKCFpcy5uYShsYXQpKSAlPiUKICBtdXRhdGUod2V0X2ZhY3RvciA9IGFzX2ZhY3Rvcih3ZXQpKSAlPiUKICBtdXRhdGUoRXZlbnRfZmFjdG9yID0gZmN0X3JlY29kZShhc19mYWN0b3IoRXZlbnQpLCBub19ldmVudCA9ICJOIiwgbmVnYXRpdmUgPSAiLSIsIHBvc2l0aXZlID0gIisiKSkgJT4lCiAgbXV0YXRlKHdldF9zdHJpbmcgPSBmY3RfcmVjb2RlKHdldF9mYWN0b3IsIHdldF9kaXNhc3RlcnMgPSAiVFJVRSIsIGRyeV9kaXNhc3RlcnMgPSAiRkFMU0UiKSkgJT4lCiAgc2VsZWN0KGxuZywgbGF0LCBFdmVudF9mYWN0b3IsIHdldF9zdHJpbmcsIG51bV9tb250aHMsIG51bV9tb250aHNfZGlzYXN0ZXIpICU+JQogIGdncGxvdCgpICsKICBnZW9tX3NmKGRhdGEgPSB3b3JsZF9tYXApICsKICBzdGF0X2Jpbl8yZChtYXBwaW5nID0gYWVzKHggPSBsbmcsIHkgPSBsYXQsIHdlaWdodCA9IG51bV9tb250aHNfZGlzYXN0ZXIvbnVtX21vbnRocyksIGJpbndpZHRoID0gYygyLDIpKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudCh0cmFucyA9ICdsb2cnLCBsb3cgPSAnd2hpdGUnLCBoaWdoID0gJ3JlZCcpICsgCiAgZmFjZXRfZ3JpZChjb2xzID0gdmFycyh3ZXRfc3RyaW5nKSwgcm93cyA9IHZhcnMoRXZlbnRfZmFjdG9yKSkgKwogIGdndGl0bGUoIjJEIEhpc3RvZ3JhbSBJbnZlcnNlIFdlaWdodGVkIGJ5IE51bSBNb250aHMiKQoKYGBgCmBgYHtyfQojIyBjYWxjdWxhdGUgcmVsYXRpdmUgcmlzayB3aXRoaW4gZWFjaCBib3gKIyMjIGNyZWF0ZSBib3hlcyBhY2MgdG8gcmVzeSBYIHJlc3kKCnJlc3kgPC0gMi41CgplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyAlPiUKICBsZWZ0X2pvaW4oZXZlbnRfbnVtX21vbnRocywgYnkgPSBjKCJFdmVudCIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGVuc29fVmFsdWUpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHdldCkpICU+JQogIGZpbHRlcighaXMubmEobGF0KSkgJT4lCiAgbXV0YXRlKHdldF9mYWN0b3IgPSBhc19mYWN0b3Iod2V0KSkgJT4lCiAgbXV0YXRlKEV2ZW50X2ZhY3RvciA9IGZjdF9yZWNvZGUoYXNfZmFjdG9yKEV2ZW50KSwgbm9fZXZlbnQgPSAiTiIsIG5lZ2F0aXZlID0gIi0iLCBwb3NpdGl2ZSA9ICIrIikpICU+JQogIG11dGF0ZSh3ZXRfc3RyaW5nID0gZmN0X3JlY29kZSh3ZXRfZmFjdG9yLCB3ZXRfZGlzYXN0ZXJzID0gIlRSVUUiLCBkcnlfZGlzYXN0ZXJzID0gIkZBTFNFIikpICU+JQogIG11dGF0ZShsYXRfYm94ID0gKGFzLmludGVnZXIobGF0KSAlLyUgcmVzeSkgKiByZXN5ICwgbG5nX2JveCA9IChhcy5pbnRlZ2VyKGxuZykgJS8lIHJlc3kpICogcmVzeSkgJT4lCiAgbXV0YXRlKGRpc19ub19mYWN0b3IgPSBhc19mYWN0b3IoYERpcyBOb2ApKSAlPiUKICBncm91cF9ieShsYXRfYm94LCBsbmdfYm94LCBFdmVudF9mYWN0b3IsIHdldF9zdHJpbmcsIGRpc19ub19mYWN0b3IpICU+JQogIHN1bW1hcml6ZShudW1fbW9udGhzID0gZmlyc3QobnVtX21vbnRocyksIG51bV9kaXNhc3Rlcl9tb250aCA9IG1lYW4obnVtX21vbnRoc19kaXNhc3RlcikpICU+JQogIGdyb3VwX2J5KGxhdF9ib3gsIGxuZ19ib3gsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZykgJT4lCiAgc3VtbWFyaXplKG51bV9tb250aHMgPSBmaXJzdChudW1fbW9udGhzKSwgbnVtX2Rpc2FzdGVyX21vbnRocyA9IHN1bShudW1fZGlzYXN0ZXJfbW9udGgpKSAlPiUKICBtdXRhdGUoZGlzYXN0ZXJfcmF0ZSA9IG51bV9kaXNhc3Rlcl9tb250aHMgLyBudW1fbW9udGhzKSAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhsYXRfYm94LCBsbmdfYm94KSwgbmFtZXNfZnJvbSA9IGMoRXZlbnRfZmFjdG9yLCB3ZXRfc3RyaW5nKSwgdmFsdWVzX2Zyb20gPSBjKGRpc2FzdGVyX3JhdGUpLCB2YWx1ZXNfZmlsbCA9IDApICU+JQogIG11dGF0ZShwb3NpdGl2ZV93ZXRfcmVsYXRpdmVfcmlzayA9IHBvc2l0aXZlX3dldF9kaXNhc3RlcnMgLyBub19ldmVudF93ZXRfZGlzYXN0ZXJzLCAKICAgICAgICAgbmVnYXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2sgPSBuZWdhdGl2ZV93ZXRfZGlzYXN0ZXJzIC8gbm9fZXZlbnRfd2V0X2Rpc2FzdGVycywgCiAgICAgICAgIHBvc2l0aXZlX2RyeV9yZWxhdGl2ZV9yaXNrID0gIHBvc2l0aXZlX2RyeV9kaXNhc3RlcnMgLyBub19ldmVudF9kcnlfZGlzYXN0ZXJzLAogICAgICAgICBuZWdhdGl2ZV9kcnlfcmVsYXRpdmVfcmlzayA9IG5lZ2F0aXZlX2RyeV9kaXNhc3RlcnMgLyBub19ldmVudF9kcnlfZGlzYXN0ZXJzKSAlPiUKICBzZWxlY3QobGF0X2JveCwgbG5nX2JveCwgcG9zaXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2ssIG5lZ2F0aXZlX3dldF9yZWxhdGl2ZV9yaXNrLCBwb3NpdGl2ZV9kcnlfcmVsYXRpdmVfcmlzaywgbmVnYXRpdmVfZHJ5X3JlbGF0aXZlX3Jpc2spICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhwb3NpdGl2ZV93ZXRfcmVsYXRpdmVfcmlzaywgbmVnYXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2ssIHBvc2l0aXZlX2RyeV9yZWxhdGl2ZV9yaXNrLCBuZWdhdGl2ZV9kcnlfcmVsYXRpdmVfcmlzayksIG5hbWVzX3RvID0gJ3Jpc2snLCB2YWx1ZXNfdG8gPSAndmFsdWUnKSAlPiUKICBtdXRhdGUocmlza19mYWN0b3IgPSBhc19mYWN0b3IocmlzayksIHZhbHVlc19jbGVhbmVkID0gaWZfZWxzZShpcy5pbmZpbml0ZSh2YWx1ZSksIDE4LCB2YWx1ZSkpICU+JQogIG11dGF0ZShyZWxhdGl2ZV9yaXNrX2NsZWFuZWQgPSBpZl9lbHNlKGlzLm5hbih2YWx1ZXNfY2xlYW5lZCksIDEsIHZhbHVlc19jbGVhbmVkKSkgJT4lCiAgbXV0YXRlKHJlbGF0aXZlX3Jpc2tfY2xlYW5lZDIgPSBpZl9lbHNlKChyZWxhdGl2ZV9yaXNrX2NsZWFuZWQpID4gMiwgMiwgcmVsYXRpdmVfcmlza19jbGVhbmVkKSkgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IHdvcmxkX21hcCkgKwogIGdlb21fdGlsZShtYXBwaW5nID0gYWVzKHggPSBsbmdfYm94LCB5ID0gbGF0X2JveCwgZmlsbCA9IHJlbGF0aXZlX3Jpc2tfY2xlYW5lZDIsIHdpZHRoID0gcmVzeSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50MihtaWRwb2ludCA9IDEsIGxpbWl0cyA9IGMoMCwgMiksIGxvdyA9ICdjeWFuJywgaGlnaCA9ICdyZWQnKSArCiAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhyaXNrX2ZhY3RvcikpKwogIGdndGl0bGUoIlJlbGF0aXZlIHJpc2sgcGxvdCB1c2luZyBjYWxjdWxhdGlvbnMgb2YgdGhlIGZvcm0gW3tudW1fZGlzYXN0ZXJzX3Bvc2l0aXZlX3dldCAvIG51bV9tb250aHNfcG9zaXRpdmV9IC8ge251bV9kaXNhc3RlcnNfbm9fZXZlbnRfd2V0IC8gbnVtX21vbnRoc19ub19ldmVudH1dIikKICAKICAKCmBgYAoKYGBge3J9CiMjIGNhbGN1bGF0ZSBwZXJjZW50IG9mIHRvdGFsIGRpc2FzdGVycyB3aXRoaW4gZWFjaCBib3gKIyMjIGNyZWF0ZSBib3hlcyAyeDIKCnJlc3kgPC0gMi41CgplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyAlPiUKICBsZWZ0X2pvaW4oZXZlbnRfbnVtX21vbnRocywgYnkgPSBjKCJFdmVudCIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGVuc29fVmFsdWUpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHdldCkpICU+JQogIGZpbHRlcighaXMubmEobGF0KSkgJT4lCiAgbXV0YXRlKHdldF9mYWN0b3IgPSBhc19mYWN0b3Iod2V0KSkgJT4lCiAgbXV0YXRlKEV2ZW50X2ZhY3RvciA9IGZjdF9yZWNvZGUoYXNfZmFjdG9yKEV2ZW50KSwgbm9fZXZlbnQgPSAiTiIsIG5lZ2F0aXZlID0gIi0iLCBwb3NpdGl2ZSA9ICIrIikpICU+JQogIG11dGF0ZSh3ZXRfc3RyaW5nID0gZmN0X3JlY29kZSh3ZXRfZmFjdG9yLCB3ZXRfZGlzYXN0ZXJzID0gIlRSVUUiLCBkcnlfZGlzYXN0ZXJzID0gIkZBTFNFIikpICU+JQogIG11dGF0ZShsYXRfYm94ID0gKGFzLmludGVnZXIobGF0KSAlLyUgcmVzeSkgKiByZXN5ICwgbG5nX2JveCA9IChhcy5pbnRlZ2VyKGxuZykgJS8lIHJlc3kpICogcmVzeSkgJT4lCiAgbXV0YXRlKGRpc19ub19mYWN0b3IgPSBhc19mYWN0b3IoYERpcyBOb2ApKSAlPiUKICBncm91cF9ieShsYXRfYm94LCBsbmdfYm94LCBFdmVudF9mYWN0b3IsIHdldF9zdHJpbmcsIGRpc19ub19mYWN0b3IpICU+JQogIHN1bW1hcml6ZShudW1fbW9udGhzID0gZmlyc3QobnVtX21vbnRocyksIG51bV9kaXNhc3Rlcl9tb250aCA9IG1lYW4obnVtX21vbnRoc19kaXNhc3RlcikpICU+JQogIGdyb3VwX2J5KGxhdF9ib3gsIGxuZ19ib3gsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZykgJT4lCiAgc3VtbWFyaXplKG51bV9tb250aHMgPSBmaXJzdChudW1fbW9udGhzKSwgbnVtX2Rpc2FzdGVyX21vbnRocyA9IHN1bShudW1fZGlzYXN0ZXJfbW9udGgpKSAlPiUKICBtdXRhdGUoZGlzYXN0ZXJfcmF0ZSA9IG51bV9kaXNhc3Rlcl9tb250aHMgLyBudW1fbW9udGhzKSAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhsYXRfYm94LCBsbmdfYm94KSwgbmFtZXNfZnJvbSA9IGMoRXZlbnRfZmFjdG9yLCB3ZXRfc3RyaW5nKSwgdmFsdWVzX2Zyb20gPSBjKGRpc2FzdGVyX3JhdGUpLCB2YWx1ZXNfZmlsbCA9IDApICU+JQogIG11dGF0ZShwb3NpdGl2ZV93ZXRfcGVyY2VudCA9IHBvc2l0aXZlX3dldF9kaXNhc3RlcnMgLyAobm9fZXZlbnRfd2V0X2Rpc2FzdGVycyArIHBvc2l0aXZlX3dldF9kaXNhc3RlcnMgKyBuZWdhdGl2ZV93ZXRfZGlzYXN0ZXJzKSAsIAogICAgICAgICBuZWdhdGl2ZV93ZXRfcGVyY2VudCA9IG5lZ2F0aXZlX3dldF9kaXNhc3RlcnMgLyAobm9fZXZlbnRfd2V0X2Rpc2FzdGVycyArIHBvc2l0aXZlX3dldF9kaXNhc3RlcnMgKyBuZWdhdGl2ZV93ZXRfZGlzYXN0ZXJzKSwgCiAgICAgICAgIHBvc2l0aXZlX2RyeV9wZXJjZW50ID0gIHBvc2l0aXZlX2RyeV9kaXNhc3RlcnMgLyAobm9fZXZlbnRfZHJ5X2Rpc2FzdGVycyArIHBvc2l0aXZlX2RyeV9kaXNhc3RlcnMgKyBuZWdhdGl2ZV9kcnlfZGlzYXN0ZXJzKSwKICAgICAgICAgbmVnYXRpdmVfZHJ5X3BlcmNlbnQgPSAgbmVnYXRpdmVfZHJ5X2Rpc2FzdGVycyAvIChub19ldmVudF9kcnlfZGlzYXN0ZXJzICsgcG9zaXRpdmVfZHJ5X2Rpc2FzdGVycyArIG5lZ2F0aXZlX2RyeV9kaXNhc3RlcnMpCiAgICAgICAgICkgJT4lCiAgc2VsZWN0KGxhdF9ib3gsIGxuZ19ib3gsIHBvc2l0aXZlX3dldF9wZXJjZW50LCBuZWdhdGl2ZV93ZXRfcGVyY2VudCwgcG9zaXRpdmVfZHJ5X3BlcmNlbnQsIG5lZ2F0aXZlX2RyeV9wZXJjZW50KSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMocG9zaXRpdmVfd2V0X3BlcmNlbnQsIG5lZ2F0aXZlX3dldF9wZXJjZW50LCBwb3NpdGl2ZV9kcnlfcGVyY2VudCwgbmVnYXRpdmVfZHJ5X3BlcmNlbnQpLCBuYW1lc190byA9ICd0eXBleScsIHZhbHVlc190byA9ICd2YWx1ZScpICU+JQogIG11dGF0ZSh0eXBlX2ZhY3RvciA9IGFzX2ZhY3Rvcih0eXBleSksIHZhbHVlcyA9IGlmX2Vsc2UoaXMubmFuKHZhbHVlKSwgMCwgdmFsdWUpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhID0gd29ybGRfbWFwKSArCiAgZ2VvbV90aWxlKG1hcHBpbmcgPSBhZXMoeCA9IGxuZ19ib3gsIHkgPSBsYXRfYm94LCBmaWxsID0gdmFsdWVzLCB3aWR0aCA9IHJlc3kpKSArCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAnd2hpdGUnLCBoaWdoID0gJ3JlZCcpICsKICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKHR5cGVfZmFjdG9yKSkrCiAgZ2d0aXRsZSgiRGlzYXN0ZXIgUGVyY2VudCBwbG90IHVzaW5nIGNhbGN1bGF0aW9ucyBvZiB0aGUgZm9ybSBbcG9zaXRpdmVfd2V0IC8gYWxsX3dldF0iKQogIAoKYGBgCgoKYGBge3J9CiMgU1BMSVQgWUVBUiBJTlRPIDIKIyBBcHIgdG8gU2VwCiMgT2N0IHRvIE1hcgojIyBjYWxjdWxhdGUgcmVsYXRpdmUgcmlzayB3aXRoaW4gZWFjaCBib3gKIyMjIGNyZWF0ZSBib3hlcyBhY2MgdG8gcmVzeSBYIHJlc3kKCnJlc3kgPC0gMi41CgpldmVudF9oYWxmX251bV9tb250aHMgPC0gZW5zb19kYXRhICU+JQogIG11dGF0ZShzcHJpbmdfc3VtbWVyeSA9IGFzX2ZhY3RvcigoTW9udGhOdW0gPj0gNCkgJiAoTW9udGhOdW0gPD0gOSkpKSAlPiUKICBtdXRhdGUoaGFsZl95ZWFyID0gZmN0X3JlY29kZShzcHJpbmdfc3VtbWVyeSwgc3ByaW5nX3N1bW1lciA9ICJUUlVFIiwgZmFsbF93aW50ZXIgPSAiRkFMU0UiKSkgJT4lCiAgZ3JvdXBfYnkoRXZlbnQsIGhhbGZfeWVhcikgJT4lCiAgc3VtbWFyaXplKG51bV9tb250aHMgPSBuKCkpCgplbWRhdF9oeWRyb2xvZ2ljYWxfZW5zbyAlPiUKICBtdXRhdGUoc3ByaW5nX3N1bW1lcnkgPSBhc19mYWN0b3IoKGVuZF9tb250aCA+PSA0KSAmIChlbmRfbW9udGggPD0gOSkpKSAlPiUKICBtdXRhdGUoaGFsZl95ZWFyID0gZmN0X3JlY29kZShzcHJpbmdfc3VtbWVyeSwgc3ByaW5nX3N1bW1lciA9ICJUUlVFIiwgZmFsbF93aW50ZXIgPSAiRkFMU0UiKSkgJT4lCiAgbGVmdF9qb2luKGV2ZW50X2hhbGZfbnVtX21vbnRocywgYnkgPSBjKCJFdmVudCIsICJoYWxmX3llYXIiKSkgJT4lCiAgZmlsdGVyKCFpcy5uYShlbnNvX1ZhbHVlKSkgJT4lCiAgZmlsdGVyKCFpcy5uYSh3ZXQpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKGxhdCkpICU+JQogIG11dGF0ZSh3ZXRfZmFjdG9yID0gYXNfZmFjdG9yKHdldCkpICU+JQogIG11dGF0ZShFdmVudF9mYWN0b3IgPSBmY3RfcmVjb2RlKGFzX2ZhY3RvcihFdmVudCksIG5vX2V2ZW50ID0gIk4iLCBuZWdhdGl2ZSA9ICItIiwgcG9zaXRpdmUgPSAiKyIpKSAlPiUKICBtdXRhdGUod2V0X3N0cmluZyA9IGZjdF9yZWNvZGUod2V0X2ZhY3Rvciwgd2V0X2Rpc2FzdGVycyA9ICJUUlVFIiwgZHJ5X2Rpc2FzdGVycyA9ICJGQUxTRSIpKSAlPiUKICBtdXRhdGUobGF0X2JveCA9IChhcy5pbnRlZ2VyKGxhdCkgJS8lIHJlc3kpICogcmVzeSAsIGxuZ19ib3ggPSAoYXMuaW50ZWdlcihsbmcpICUvJSByZXN5KSAqIHJlc3kpICU+JQogIG11dGF0ZShkaXNfbm9fZmFjdG9yID0gYXNfZmFjdG9yKGBEaXMgTm9gKSkgJT4lCiAgZ3JvdXBfYnkobGF0X2JveCwgbG5nX2JveCwgRXZlbnRfZmFjdG9yLCB3ZXRfc3RyaW5nLCBkaXNfbm9fZmFjdG9yLCBoYWxmX3llYXIpICU+JQogIHN1bW1hcml6ZShudW1fbW9udGhzID0gZmlyc3QobnVtX21vbnRocyksIG51bV9kaXNhc3Rlcl9tb250aCA9IG1lYW4obnVtX21vbnRoc19kaXNhc3RlcikpICU+JQogIGdyb3VwX2J5KGxhdF9ib3gsIGxuZ19ib3gsIEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZywgaGFsZl95ZWFyKSAlPiUKICBzdW1tYXJpemUobnVtX21vbnRocyA9IGZpcnN0KG51bV9tb250aHMpLCBudW1fZGlzYXN0ZXJfbW9udGhzID0gc3VtKG51bV9kaXNhc3Rlcl9tb250aCkpICU+JQogIG11dGF0ZShkaXNhc3Rlcl9yYXRlID0gbnVtX2Rpc2FzdGVyX21vbnRocyAvIG51bV9tb250aHMpICU+JQogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBjKGxhdF9ib3gsIGxuZ19ib3gsIGhhbGZfeWVhciksIG5hbWVzX2Zyb20gPSBjKEV2ZW50X2ZhY3Rvciwgd2V0X3N0cmluZyksIHZhbHVlc19mcm9tID0gYyhkaXNhc3Rlcl9yYXRlKSwgdmFsdWVzX2ZpbGwgPSAwKSAlPiUKICBtdXRhdGUocG9zaXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2sgPSBwb3NpdGl2ZV93ZXRfZGlzYXN0ZXJzIC8gbm9fZXZlbnRfd2V0X2Rpc2FzdGVycywgCiAgICAgICAgIG5lZ2F0aXZlX3dldF9yZWxhdGl2ZV9yaXNrID0gbmVnYXRpdmVfd2V0X2Rpc2FzdGVycyAvIG5vX2V2ZW50X3dldF9kaXNhc3RlcnMsIAogICAgICAgICBwb3NpdGl2ZV9kcnlfcmVsYXRpdmVfcmlzayA9ICBwb3NpdGl2ZV9kcnlfZGlzYXN0ZXJzIC8gbm9fZXZlbnRfZHJ5X2Rpc2FzdGVycywKICAgICAgICAgbmVnYXRpdmVfZHJ5X3JlbGF0aXZlX3Jpc2sgPSBuZWdhdGl2ZV9kcnlfZGlzYXN0ZXJzIC8gbm9fZXZlbnRfZHJ5X2Rpc2FzdGVycykgJT4lCiAgc2VsZWN0KGxhdF9ib3gsIGxuZ19ib3gsIGhhbGZfeWVhciwgcG9zaXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2ssIG5lZ2F0aXZlX3dldF9yZWxhdGl2ZV9yaXNrLCBwb3NpdGl2ZV9kcnlfcmVsYXRpdmVfcmlzaywgbmVnYXRpdmVfZHJ5X3JlbGF0aXZlX3Jpc2spICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhwb3NpdGl2ZV93ZXRfcmVsYXRpdmVfcmlzaywgbmVnYXRpdmVfd2V0X3JlbGF0aXZlX3Jpc2ssIHBvc2l0aXZlX2RyeV9yZWxhdGl2ZV9yaXNrLCBuZWdhdGl2ZV9kcnlfcmVsYXRpdmVfcmlzayksIG5hbWVzX3RvID0gJ3Jpc2snLCB2YWx1ZXNfdG8gPSAndmFsdWUnKSAlPiUKICBtdXRhdGUocmlza19mYWN0b3IgPSBhc19mYWN0b3IocmlzayksIHZhbHVlc19jbGVhbmVkID0gaWZfZWxzZShpcy5pbmZpbml0ZSh2YWx1ZSksIDE4LCB2YWx1ZSkpICU+JQogIG11dGF0ZShyZWxhdGl2ZV9yaXNrX2NsZWFuZWQgPSBpZl9lbHNlKGlzLm5hbih2YWx1ZXNfY2xlYW5lZCksIDEsIHZhbHVlc19jbGVhbmVkKSkgJT4lCiAgbXV0YXRlKHJlbGF0aXZlX3Jpc2tfY2xlYW5lZF90cnVuY2F0ZWRhdDIgPSBpZl9lbHNlKChyZWxhdGl2ZV9yaXNrX2NsZWFuZWQpID4gMiwgMiwgcmVsYXRpdmVfcmlza19jbGVhbmVkKSkgJT4lCiAgc2VsZWN0KGxhdF9ib3gsIGxuZ19ib3gsIGhhbGZfeWVhciwgcmlza19mYWN0b3IsIHJlbGF0aXZlX3Jpc2tfY2xlYW5lZCwgcmVsYXRpdmVfcmlza19jbGVhbmVkX3RydW5jYXRlZGF0MikgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fc2YoZGF0YSA9IHdvcmxkX21hcCkgKwogIGdlb21fdGlsZShtYXBwaW5nID0gYWVzKHggPSBsbmdfYm94LCB5ID0gbGF0X2JveCwgZmlsbCA9IHJlbGF0aXZlX3Jpc2tfY2xlYW5lZF90cnVuY2F0ZWRhdDIsIHdpZHRoID0gcmVzeSkpICsKICBzY2FsZV9maWxsX2dyYWRpZW50MihtaWRwb2ludCA9IDEsIGxpbWl0cyA9IGMoMCwgMiksIGxvdyA9ICdjeWFuJywgaGlnaCA9ICdyZWQnKSArCiAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhyaXNrX2ZhY3RvciksIGNvbHMgPSB2YXJzKGhhbGZfeWVhcikpKwogIGdndGl0bGUoIkhhbGYgeWVhciBSZWxhdGl2ZSByaXNrIHBsb3QgdXNpbmcgY2FsY3VsYXRpb25zIG9mIHRoZSBmb3JtIFt7bnVtX2Rpc2FzdGVyc19wb3NpdGl2ZV93ZXQgLyBudW1fbW9udGhzX3Bvc2l0aXZlfSAvIHtudW1fZGlzYXN0ZXJzX25vX2V2ZW50X3dldCAvIG51bV9tb250aHNfbm9fZXZlbnR9XSIpCiAgCiAgCgpgYGA=